#include "../include/default_handler.h"
#include "../include/global_settings.h"
#include "../include/check_crash.h"
#include "../include/crash_handler.h"
#include "../include/event.h"
#include <cmath>
#include <stdlib.h>

int evt_motion_id, evt_check_id, evt_respawn_id, evt_animate_id;

extern "C" void defaultHandlerInit()
{
	evt_motion_id = registerEventType(ehMotion);
	evt_check_id = registerEventType(ehCheck);
	evt_respawn_id = registerEventType(ehRespawn);
	evt_animate_id = registerEventType(ehAnimate);
}

extern "C" void ehMotion(pEventInfo info)
{
	if(!findObject(info->obj1))return;

	pObject o =  getData(info->obj1);

	if(!o->fixed)
	{
		o->speed.x += o->acc.x;
		o->speed.y += o->acc.y;

		if(fabs(o->speed.x) < ACC_X)o->speed.x = 0;
		else if(o->speed.x > MAX_SPEED_X)o->speed.x = MAX_SPEED_X;
		else if(o->speed.x < -MAX_SPEED_X)o->speed.x = -MAX_SPEED_X;

		if(fabs(o->speed.y) < ACC_X)o->speed.y = 0;
		else if(o->speed.y > MAX_SPEED_Y)o->speed.y = MAX_SPEED_Y;
		else if(o->speed.y < -MAX_SPEED_Y)o->speed.y = -MAX_SPEED_Y;

		o->pos.x += o->speed.x;
		o->pos.y += o->speed.y;

		o->acc.y = -ACC_Y;
		o->acc.x = 0.0f;

		if (o->pos.y <= -1) 
		{
			if(o->alive)Die(info->obj1);
			else if(o->obj_type != MARIO)removeObject(info->obj1);
		}
		if(o->pos.x + o->size.x < -1.0f)o->pos.x = 1.0f - PRECISION;
		if(o->pos.x > 1.0f)o->pos.x = -1.0f - o->size.x + PRECISION;
	}
	info->time_interval = 1;
}

extern "C" void ehRespawn(pEventInfo info)
{
	if(!findObject(info->obj1))return;

	pObject pobj = getData(info->obj1);
	pobj->pos.x = (float)rand() / RAND_MAX * 2 - 1;
	pobj->pos.y = (float)rand() / RAND_MAX * 2 - 1;
	pobj->speed.x = 0;
	pobj->speed.y = 0;
	pobj->acc.x = 0;
	pobj->acc.y = 0;
	pobj->weapon = 0;
	pobj->alive = 1;
	pobj->fixed = 0;
	pobj->solid = SOLID;
	pobj->size.y = 0.1f;
}

extern "C" void ehCheck(pEventInfo info)
{
	adjustPos();
	checkCrash();

	info->time_interval = 1;
}

extern "C" void ehAnimate(pEventInfo info)
{
	if(!findObject(info->obj1))return;

	pObject mario = getData(info->obj1);
	if(mario->alive)
	{
	    mario->img_index %= 4;
		if(fabs(mario->speed.y) <= ACC_Y)
		{
			if(mario->speed.x < -ACC_X)
			{
				if(mario->img_index != 2 && mario->img_index != 3)mario->img_index = 2;
			}
			else if(mario->speed.x > ACC_X)
			{
				if(mario->img_index != 0 && mario->img_index != 1)mario->img_index = 0;
			}
			else
				mario->img_index |= 1;

			mario->img_index ^= 1;
		}
		else
		{
			if(fabs(mario->speed.x) <= ACC_X)mario->img_index &= (~1);
			else
				mario->img_index |= 1;
		}
		mario->img_index += getMarioId(info->obj1) * 4;
	}
	info->time_interval = 6;
}
